package com.demo.wy;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.demo.wy.util.JWTUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT基础功能演示类
 * 演示了JWT的基本使用方法，包括：
 * 1. JWT的创建和验证
 * 2. JWT各组成部分的解析
 * 3. JWT异常处理
 * 4. 使用工具类简化JWT操作
 */
public class JWTDemo {
    public static void main(String[] args) {
        // 1. 基本的JWT生成和验证
        demoBasicJWT();

        // 2. JWT的组成部分解析
        demoJWTParts();

        // 3. 异常处理演示
        demoJWTExceptions();

        // 4. 使用工具类生成和验证JWT
        demoJWTUtils();
    }

    /**
     * 演示JWT的基本创建和验证流程
     * 包括：
     * 1. 创建包含各种声明的JWT
     * 2. 使用密钥进行签名
     * 3. 验证JWT的有效性
     */
    private static void demoBasicJWT() {
        System.out.println("=== 基本JWT演示 ===");
        try {
            // 创建JWT
            String token = JWT.create()
                    .withIssuer("auth0") // 发行人
                    .withSubject("用户信息") // 主题
                    .withAudience("client") // 受众
                    .withIssuedAt(new Date()) // 签发时间
                    .withExpiresAt(new Date(System.currentTimeMillis() + 5000)) // 过期时间：5秒
                    .withClaim("userId", "12345") // 自定义声明
                    .withClaim("username", "张三")
                    .withClaim("role", "admin")
                    .sign(Algorithm.HMAC256("secret")); // 签名

            System.out.println("生成的Token: " + token);

            // 验证JWT
            DecodedJWT jwt = JWT.require(Algorithm.HMAC256("secret"))
//                    .withIssuer("auth0")
                    .build()
                    .verify(token);

            System.out.println("Token验证成功!");
        } catch (Exception e) {
            System.out.println("Token操作异常: " + e.getMessage());
        }
    }

    /**
     * 演示JWT的三个组成部分的解析
     * 包括：
     * 1. Header（头部）的解析
     * 2. Payload（负载）的解析
     * 3. Signature（签名）的获取
     */
    private static void demoJWTParts() {
        System.out.println("\n=== JWT组成部分解析演示 ===");
        try {
            String token = JWT.create()
                    .withHeader(new HashMap<String, Object>() {{
                        put("typ", "JWT");
                        put("alg", "HS256");
                    }})
                    .withClaim("userId", "12345")
                    .withExpiresAt(new Date(System.currentTimeMillis() + 5000))
                    .sign(Algorithm.HMAC256("secret"));

            DecodedJWT jwt = JWT.decode(token);

            // 解析Header
            System.out.println("Header:");
            System.out.println("  类型: " + jwt.getType());
            System.out.println("  算法: " + jwt.getAlgorithm());

            // 解析Payload
            System.out.println("Payload:");
            System.out.println("  用户ID: " + jwt.getClaim("userId").asString());
            System.out.println("  过期时间: " + jwt.getExpiresAt());

            // 获取签名
            System.out.println("Signature: " + jwt.getSignature());
        } catch (Exception e) {
            System.out.println("Token解析异常: " + e.getMessage());
        }
    }

    /**
     * 演示JWT常见异常的处理
     * 包括：
     * 1. 令牌过期异常的处理
     * 2. 签名验证失败异常的处理
     */
    private static void demoJWTExceptions() {
        System.out.println("\n=== JWT异常处理演示 ===");

        try {
            // 创建一个已过期的token
            String expiredToken = JWT.create()
                    .withClaim("userId", "12345")
                    .withExpiresAt(new Date(System.currentTimeMillis() - 1000)) // 过期时间设置为1秒前
                    .sign(Algorithm.HMAC256("secret"));

            // 尝试验证过期的token
            JWT.require(Algorithm.HMAC256("secret"))
                    .build()
                    .verify(expiredToken);
        } catch (TokenExpiredException e) {
            System.out.println("Token已过期: " + e.getMessage());
        } catch (JWTVerificationException e) {
            System.out.println("Token验证失败: " + e.getMessage());
        }

        try {
            // 使用错误的签名密钥验证
            String token = JWT.create()
                    .withClaim("userId", "12345")
                    .sign(Algorithm.HMAC256("correctSecret"));

            JWT.require(Algorithm.HMAC256("wrongSecret"))
                    .build()
                    .verify(token);
        } catch (JWTVerificationException e) {
            System.out.println("签名验证失败: " + e.getMessage());
        }
    }

    /**
     * 演示使用JWTUtils工具类简化JWT操作
     * 包括：
     * 1. 使用工具类生成token
     * 2. 验证token的有效性
     * 3. 解析token中的payload信息
     */
    private static void demoJWTUtils() {
        System.out.println("\n=== JWTUtils工具类演示 ===");

        try {
            // 准备payload数据
            Map<String, String> payload = new HashMap<>();
            payload.put("userId", "12345");
            payload.put("username", "张三");
            payload.put("role", "admin");

            // 生成token
            String token = JWTUtils.getToken(payload);
            System.out.println("生成的Token: " + token);

            // 验证token
            JWTUtils.verify(token);
            System.out.println("Token验证成功!");

            // 解析token中的payload
            DecodedJWT jwt = JWTUtils.getToken(token);
            Map<String, Claim> claims = jwt.getClaims();
            System.out.println("解析的Payload:");
            claims.forEach((key, value) -> {
                System.out.println("  " + key + ": " + value.asString());
            });
        } catch (Exception e) {
            System.out.println("Token操作异常: " + e.getMessage());
        }
    }
}